package com.borya.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.borya.constant.RedisConstant;
import com.borya.dao.MerchantDAO;
import com.borya.dao.MessageDAO;
import com.borya.dao.RegistOrderInfoDAO;
import com.borya.dao.UserDAO;
import com.borya.filter.auth.AppType;
import com.borya.filter.auth.OsType;
import com.borya.framework.annotation.Autowired;
import com.borya.framework.util.ObjectUtils;
import com.borya.model.db.*;
import com.borya.model.entity.FileInfo;
import com.borya.model.entity.Gps2Address;
import com.borya.model.entity.SelfRegistering;
import com.borya.model.entity.UserDataModel;
import com.borya.model.enumcation.MerchantPowerLimit;
import com.borya.service.BaseService;
import com.borya.statuscode.StatusCode;
import com.borya.util.*;
import com.borya.util.AliOSSUtil.UploadResult;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import java.io.File;
import java.time.Clock;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public abstract class BaseServiceImpl implements BaseService {

    private Logger log = Logger.getLogger(getClass());
    private Random random = new Random();
    @Autowired("merchantDAO")
    private MerchantDAO merchantDAO;
    @Autowired("userDAOImpl")
    private UserDAO userDAO;

    @Autowired("messageDAO")
    private MessageDAO messageDAO;

    @Autowired("registOrderInfoDAO")
    private RegistOrderInfoDAO registOrderInfoDAO;

    /**
     * 创建授权牌
     *
     * @param shqpInfo
     * @param year
     * @param month
     * @param day
     * @param type     1新增 2修改
     * @return
     */
    protected boolean makeShqpImg(ShqpInfo shqpInfo, String year, String month, String day, int type, int sourceType) {
        String date = DateUtils.format(shqpInfo.getModifyTime(), "yyyyMMddHHmmss");
        String shqpName = "shqp" + date + shqpInfo.getDealerId() + ".jpg";
        FileInfo newInstance = FileInfo.newInstance(Constant.SpecialTag.SHQP, shqpInfo.getDealerId(), shqpName);
        File fle = new File(newInstance.getParentPath());
        if (!fle.exists()) {
            fle.mkdirs();
        }
        final String filePath = newInstance.getFilePath();
        ImageUtils.makeShqp(filePath, shqpInfo.getShpqId(), year, month, day, sourceType);
        UploadResult upload = AliOSSUtil.upload(filePath, newInstance.getRelatePath());
        final boolean flag = upload.isFlag();
        if (!flag) {
            log.error("上传oss失败，本地路径：" + filePath);
        } else {
            new File(filePath).delete();
        }
        shqpInfo.setShqpUrl(upload.getNetUrl());

        boolean r = merchantDAO.updShqpInfo(shqpInfo, type);
        log.info(shqpInfo.getDealerId() + "授权牌相关信息处理结果:" + r);
        return r;
    }


//    protected String getImgUrlPath(String dir, String imgName, String typeStr){
//        if(StringUtils.isNotBlank(imgName)){
//            return Constant.ums_url +dir.substring(dir.indexOf(typeStr));
//        }
//        return null;
//    }

    /**
     * 激活结果给商户发送消息
     *
     * @param userId
     * @param result 1激活成功2激活失败3授权牌续约成功4授权牌到期提醒
     */
    protected void sendMsg(String userId, String remarks, int result, int isManage) {
        Message msg = new Message();
        final long curTime = Clock.systemDefaultZone().millis();
        msg.setMsgId(StringUtil.getMsgId(curTime));
        msg.setMsgType(Message.MessageType.BUSINESS);
        msg.setSender("system");
        msg.setReceiver(userId);
        msg.setCreatTime(curTime);
        msg.setExpTime(curTime + 30 * 24 * 60 * 60 * 1000);
        StringBuilder content = new StringBuilder(256);
        switch (result) {
            case 1:
                content.append("{");
                content.append("\"type\":243");
                content.append(",\"title\": \"商户绑定设备结果通知\"");
                content.append(",\"annex\":[]");
                content.append(",\"content\":\"");
                content.append("尊敬的用户,您已于");
                content.append(DateUtils.format(curTime, "yyyy-MM-dd HH:mm:ss"));
                content.append("成功绑定设备,现在可以去开卡啦！");
                if (isManage == 1)
                {
                    content.append("您可以至发现-流转申请 做专营号段流转申请。");
                }
                content.append("\"");
                content.append(",\"redirectUrl\":\"\"");
                content.append("}");

                break;
            case 2:
                content.append("{");
                content.append("\"type\":244");
                content.append(",\"title\": \"商户绑定设备结果通知\"");
                content.append(",\"annex\":[]");
                content.append(",\"content\":\"");
                content.append("尊敬的用户,您的绑定设备申请于");
                content.append(DateUtils.format(curTime, "yyyy-MM-dd HH:mm:ss"));
                content.append("被拒绝，原因是：");
                content.append(remarks);
                content.append("。请按照要求，重新申请绑定设备。");
                content.append("\"");
                content.append(",\"redirectUrl\":\"\"");
                content.append("}");
                break;
            default:
                break;
        }
        log.info("send msg:" + content.toString());
        msg.setContent(content.toString());

        messageDAO.save(msg);
    }

    /**
     * @param userId
     */
    protected void sendMsgNormal(String userId, String title, String contentStr, String msgType) {
        Message msg = new Message();
        final long curTime = Clock.systemDefaultZone().millis();
        msg.setMsgId(StringUtil.getMsgId(curTime));
        msg.setMsgType(Message.MessageType.BUSINESS);
        msg.setSender("system");
        msg.setReceiver(userId);
        msg.setCreatTime(curTime);
        msg.setExpTime(curTime + 30 * 24 * 60 * 60 * 1000);
        StringBuilder content = new StringBuilder(256);
        content.append("{");
        content.append("\"type\":").append(msgType);
        content.append(",\"title\": \"").append(title).append("\"");
        content.append(",\"annex\":[]");
        content.append(",\"content\":\"");
        content.append(contentStr);
        content.append("\"");
        content.append(",\"redirectUrl\":\"\"");
        content.append("}");
        log.info("send msg:" + content.toString());
        msg.setContent(content.toString());

        messageDAO.save(msg);
    }

    /**
     * 获取授权牌信息
     **/
    protected void addShqpInfo(String dealerId, StringBuilder sb, int sourceType) {
        ShqpInfo shqpInfo = merchantDAO.getShqpInfo(dealerId);
        if (shqpInfo == null
                || shqpInfo.getShqpEndTime() == 0) {
            sb.append("\"endDate\":\"0\"");
            sb.append(",\"url\":\"\"");
            sb.append(",\"state\":\"0\"");
            sb.append(",\"renewStr\":\"\"");
            return;
        }
        int nowDate = Integer.parseInt(DateUtils.format(Clock.systemDefaultZone().millis(), "yyyyMMdd"));
        int endDate = shqpInfo.getShqpEndTime();
        int twoMonAgo = Integer.parseInt(DateUtils.getExpectDate(endDate + "", 0, -2, 0, "yyyyMMdd"));
        final String endDateStr = endDate + "";
        final String year = endDateStr.substring(0, 4);
        final String month = endDateStr.substring(4, 6);
        final String day = endDateStr.substring(6, 8);

        if (ObjectUtils.isNullOrEmpty(shqpInfo.getShqpUrl())) {
            //只有结束日期 却没有受理单
            if (ObjectUtils.isNullOrEmpty(shqpInfo.getShpqId())) {
                log.info("授权牌无编号，" + shqpInfo.toString());
                sb.append("\"endDate\":\"0\"");
                sb.append(",\"url\":\"\"");
                sb.append(",\"state\":\"0\"");
                sb.append(",\"renewStr\":\"\"");
                return;
            }
            shqpInfo.setModifyTime(Clock.systemDefaultZone().millis());
            boolean makeShqp = makeShqpImg(shqpInfo, year, month, day, 2, sourceType);
            if (!makeShqp) {
                log.info("授权牌生成失败，" + shqpInfo.toString());
                sb.append("\"endDate\":\"0\"");
                sb.append(",\"url\":\"\"");
                sb.append(",\"state\":\"0\"");
                sb.append(",\"renewStr\":\"\"");
                return;
            }
        }
        sb.append("\"endDate\":\"").append(year + "-" + month + "-" + day).append("\"");
        sb.append(",\"url\":\"").append(AliOSSUtil.generatePresignedUrl(shqpInfo.getShqpUrl())).append("\"");


        String state, renewStr;
        if (nowDate <= twoMonAgo) {
            state = "1";
            renewStr = "";
        } else if (nowDate > twoMonAgo && nowDate <= endDate) {
            state = "2";
            renewStr = new StringBuilder("温馨提示：您的授权牌将在").append(year).append("年")
                    .append(month).append("月").append(day).append("日到期，请尽快签名并点击下方“授权牌续约”。")
                    .append("续约后授权牌有效期限为申请授权牌续约日起有效期一年。").toString();
        } else {
            state = "3";
            renewStr = new StringBuilder("温馨提示：您的授权牌在").append(year).append("年")
                    .append(month).append("月").append(day).append("日已到期，请尽快签名并点击下方“授权牌续约”。")
                    .append("续约后授权牌有效期限为申请授权牌续约日起有效期一年。").toString();
        }

        sb.append(",\"state\":\"").append(state).append("\"");
        sb.append(",\"renewStr\":\"").append(renewStr).append("\"");

    }


    protected String geDealerId(String companyName, String userName, String phone) {
        JSONObject json = new JSONObject();
        json.put("Name", companyName);
        json.put("LinkMan", userName);
        json.put("PhoneNumber", phone);
        final long time = Clock.systemDefaultZone().millis();
        final String orderId = phone + DateUtils.format(time, "yyyyMMddHHmmss") + StringUtil.randomString(6);
        json.put("orderId", orderId);
        final String GET_DEALERID_URL = Constant.GET_DEALERID_URL;
        String result = HTTPUtils.sendPost(GET_DEALERID_URL, json.toJSONString());
        log.info("getDealerId url:" + GET_DEALERID_URL + ",data:" + json + ",result:" + result);
        if (result != null) {
            return result;
        }
        //请求超时 redis等待3分钟
        log.info("获取dealerId返回null,等待3分钟:" + orderId);
        for (; ; ) {
            LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(5));
            result = merchantDAO.getDealerIdResult(orderId);
            if (result != null) {
                return result;
            }
            long time2 = Clock.systemDefaultZone().millis();
            if (time2 - time > 150000) {
                log.info(orderId + "获取dealerId长时间未得到结果");
                return null;
            }
        }
    }

    protected void addSpecialDealerModel(String popChannel, String dealerId, String dealerName) {
        //预存卡
        addMonoSpecialModel(popChannel, dealerId, dealerName);
        //大众号
        addNoamalSpecialModel(popChannel, dealerId, dealerName);
    }

    /**
     * 预存卡权益套餐模式继承
     * @param popChannel
     * @param dealerId
     * @param dealerName
     */
    private void addMonoSpecialModel(String popChannel, String dealerId, String dealerName){
        List<SpecialModel> modelList = userDAO.specialModel(popChannel);
        if (Objects.isNull(modelList)) {
            log.error("specialModel return null,popChannel:" + popChannel + ",dealerId:" + dealerId);
            return;
        }
        if (modelList.isEmpty()) {
            return;
        }
        boolean add = userDAO.addSpecialDealerModel(modelList, dealerId, dealerName);
        log.debug(dealerId + "  addSpecialDealerModel return " + add);
    }
    /**
     * 大众号权益套餐模式继承
     * @param popChannel
     * @param dealerId
     * @param dealerName
     */
    private void addNoamalSpecialModel(String popChannel, String dealerId, String dealerName){
        List<SpecialModel> modelList = userDAO.specialModelNoamral(popChannel);
        if (Objects.isNull(modelList)) {
            log.error("specialModelNoamral return null,popChannel:" + popChannel + ",dealerId:" + dealerId);
            return;
        }
        if (modelList.isEmpty()) {
            return;
        }
        boolean add = userDAO.addSpecialDealerModelNoamal(modelList, dealerId, dealerName);
        log.debug(dealerId + "  addSpecialDealerModelNoamal return " + add);
    }

    /**
     * 添加限制记录
     * @param s
     * @param modelInfo
     */
    protected void addLimitPower(SelfRegistering s, ModelInfo modelInfo){
        if(modelInfo.getLimitLiantong() == 0 && modelInfo.getLimitMall() == 0){
            return;
        }
        final long nowTime = Clock.systemDefaultZone().millis();
        List<TbMerchantPowerLimit> limitList = new ArrayList<>();
        if(modelInfo.getLimitMall() == 1){
            TbMerchantPowerLimit limit = new TbMerchantPowerLimit(s.getDealer_id(),
                    MerchantPowerLimit.MALL.getPower(),nowTime,"继承");
            limitList.add(limit);
        }
        if(modelInfo.getLimitLiantong() == 1){
            TbMerchantPowerLimit limit = new TbMerchantPowerLimit(s.getDealer_id(),
                    MerchantPowerLimit.LIANTONG.getPower(),nowTime,"继承");
            limitList.add(limit);
        }
        if(limitList.isEmpty()){
            log.warn("数据异常，"+modelInfo);
            return;
        }
        boolean r = userDAO.addLimitPower(limitList);
        log.info(String.format("新增限制权限power,%s,结果:%s",limitList,r));
    }


    protected void setAddress(Gps2Address gps2Address) {
        TransAddr.getAddress(gps2Address, getApiAk());
    }


    protected String getApiAk() {
        final String aks = userDAO.redis_get(RedisConstant.BAIDU_API_AK);
        if (ObjectUtils.isNullOrEmpty(aks)) {
            return Constant.ApiConf.BAIDU_MAP_APK;
        }
        List<String> list = Stream.of(aks.split(",")).collect(Collectors.toList());
        return list.stream().skip(random.nextInt(list.size())).findAny().get();
    }

    protected boolean imgUploadOssAndRemoveDir(String relatePath) {
        final String filePath = Constant.IMG_SAVE_PATH + relatePath;
        File file = new File(filePath);
        if (!file.exists()) {
            log.info("当前路径图片不存在，不能上传至oss");
            return false;
        }
        UploadResult upload = AliOSSUtil.upload(filePath, relatePath);
        if (!upload.isFlag()) {
            log.info("上传图片至oss失败，图片路径：" + filePath);
            return false;
        }
        file.delete();
        return true;
    }


    /**
     * 新用户欢迎消息
     *
     * @param userId
     * @param isMain
     * @param detailType
     */
    protected void addWelcomeMsg(String userId, int isMain, int detailType) {
        //默认写卡盟
        final int detailTypeEnd;
        if (detailType == 0) {
            detailTypeEnd = 1;
        } else {
            detailTypeEnd = detailType;
        }
        List<WelcomeMsg> list = messageDAO.allWelComeMsg();
        if (ObjectUtils.isNullOrEmpty(list)) {
            log.warn("allWelComeMsg return nothing," + list);
            return;
        }
        List<WelcomeMsg> mapList = list.stream().filter(x -> x.getFlag() == 1 && x.getIsMain() == isMain && x.getDetailType() == detailTypeEnd)
                .sorted(Comparator.comparing(WelcomeMsg::getId)).collect(Collectors.toList());
        if (mapList.isEmpty()) {
            log.info(String.format("无欢迎消息，userId:%s,isMain:%s,detailType:%s", userId, isMain, detailType));
            return;
        }
        Message msg = new Message();
        final long curTime = Clock.systemDefaultZone().millis();
        msg.setReceiver(userId);
        msg.setCreatTime(curTime);
        messageDAO.addWelcomeMsg(msg, mapList);
    }

    /**
     * 获取模式变化后的值
     *
     * @param oldModel 老模式
     * @param addModel 新增模式
     * @return
     */
    protected static String getModelStr(String oldModel, String addModel) {
        if (ObjectUtils.isNullOrEmpty(oldModel)) {
            return addModel;
        }
        if (ObjectUtils.isNullOrEmpty(addModel)) {
            return oldModel;
        }
        List<String> newModels = new ArrayList<>();
        StringBuilder sb = new StringBuilder(256);
        for (String each : (oldModel + "," + addModel).split(",")) {
            if (ObjectUtils.isNullOrEmpty(each)) {
                continue;
            }
            if (newModels.contains(each)) {
                continue;
            }
            newModels.add(each);
            if (sb.length() > 0) {
                sb.append(",");
            }
            sb.append(each);
        }
        return sb.toString();
    }


    protected String getUserId() {
        return DateUtils.format(Clock.systemDefaultZone().millis(),"yyMMdd") + StringUtil.randomNumberString(6);
    }

    protected boolean sendMsg(String phone, String content) {
        log.info(phone + content);
        return SmsUtils.sendMsg(phone, content);
    }

    protected Integer getBackgroundVersion(String appType, String osType) {
        if (Objects.equals(AppType.KA_MENG.getType(), appType)) {
            if (Integer.toString(OsType.IOS.getType()).equals(osType)) {
                return Integer.parseInt(Constant.MERCHANT_OPERATION_KA_MENG_IOS);
            } else {
                return Integer.parseInt(Constant.MERCHANT_OPERATION_KA_MENG_ANDROID);
            }
        } else if (Objects.equals(AppType.XI_NIU.getType(), appType)) {
            if (Integer.toString(OsType.IOS.getType()).equals(osType)) {
                return Integer.parseInt(Constant.MERCHANT_OPERATION_XI_NIU_IOS);
            } else {
                return Integer.parseInt(Constant.MERCHANT_OPERATION_XI_NIU_ANDROID);
            }
        } else if (Objects.equals(AppType.YI_JIA.getType(), appType)) {
            if (Integer.toString(OsType.IOS.getType()).equals(osType)) {
                return Integer.parseInt(Constant.MERCHANT_OPERATION_YI_JIA_IOS);
            } else {
                return Integer.parseInt(Constant.MERCHANT_OPERATION_YI_JIA_ANDROID);
            }
        } else if (Objects.equals(AppType.QUAN_WANG_TONG.getType(), appType)) {
            if (Integer.toString(OsType.IOS.getType()).equals(osType)) {
                return Integer.parseInt(Constant.MERCHANT_OPERATION_QUAN_WANG_TONG_IOS);
            } else {
                return Integer.parseInt(Constant.MERCHANT_OPERATION_QUAN_WANG_TONG_ANDROID);
            }
        } else if (Objects.equals(AppType.JU_LIAN.getType(), appType)) {
            if (Integer.toString(OsType.IOS.getType()).equals(osType)) {
                return Integer.parseInt(Constant.MERCHANT_OPERATION_JU_LIAN_IOS);
            } else {
                return Integer.parseInt(Constant.MERCHANT_OPERATION_JU_LIAN_ANDROID);
            }
        } else {
            return 0;
        }
    }

    protected String checkIdCardAndBusinessLicence(String merchantType, String identityCard, User user, String businessLicence) {
        // 校验身份证号码、企业营业执照已激活用户数量
        int idCardCount = 0; // 身份证激活商户数量
        if ("1".equals(merchantType)) { // 企业
            // 通过身份证号码获取在途激活用户
            List<RegistOrderInfo> registOrderInfoList = registOrderInfoDAO.getRegistorAuditListByIdCard(identityCard, user.getDetailType(), 1);
            if (Objects.nonNull(registOrderInfoList)) {
                idCardCount += registOrderInfoList.size();
            }
            // 通过身份证号码获取已激活用户
            List<UserDataModel> userDetailList = userDAO.getUserDetailListByIdCard(identityCard, user.getDetailType());
            if (Objects.nonNull(userDetailList)) {
                idCardCount += userDetailList.size();
            }
            if (idCardCount >= Constant.COMPANY_IDENTITY_REGISTER_COUNT) {
                log.error("该身份证号码可激活商户数量达到上限,idCard为" + identityCard);
                return StatusCode.SYSTEM_EXCEPTION.toJSON("该身份证号码可激活商户数量达到上限,如需操作请联系管理员");
            }
            // 校验企业营业执照编号
            String checkBusinessLicence = checkBusinessLicence(businessLicence, user);
            if (StringUtils.isNotBlank(checkBusinessLicence)) {
                return checkBusinessLicence;
            }
        } else { // 个人
            // 通过身份证号码获取已激活用户
            List<UserDataModel> userDetailList = userDAO.getUserDetailListByIdCard(identityCard, user.getDetailType());
            if (Objects.nonNull(userDetailList)) {
                idCardCount += userDetailList.size();
            }
            // 通过身份证号码获取在途激活用户
            List<RegistOrderInfo> list = registOrderInfoDAO.getRegistorAuditListByIdCard(identityCard, user.getDetailType(), 1);
            if (Objects.nonNull(list)) {
                idCardCount += list.size();
            }
            if (idCardCount >= Constant.PERSONAL_IDENTITY_REGISTER_COUNT) {
                log.error("该身份证号码可激活商户数量达到上限,idCard为" + identityCard);
                return StatusCode.SYSTEM_EXCEPTION.toJSON("该身份证号码可激活商户数量达到上限,如需操作请联系管理员");
            }
        }

        return "";
    }

    protected String checkBusinessLicence(String businessLicence, User user) {
        int businessLicenceCount = 0; // 营业执照激活商户数量
        // 通过营业执照编号获取已激活用户
        List<Merchant> list = merchantDAO.getMerchantByBusinessLicence(businessLicence, user.getDetailType());
        if (Objects.nonNull(list)) {
            businessLicenceCount += list.size();
        }
        // 通过营业执照编号获取在途激活用户
        List<RegistOrderInfo> infoList = registOrderInfoDAO.getRegistorAuditListByIdCard(businessLicence, user.getDetailType(), 2);
        if (Objects.nonNull(infoList)) {
            businessLicenceCount += infoList.size();
        }
        if (businessLicenceCount >= Constant.COMPANY_BUSINESS_LICENSE_REGISTER_COUNT) {
            log.error("该营业执照可激活商户数量达到上限,businessLicence为" + businessLicence);
            return StatusCode.SYSTEM_EXCEPTION.toJSON("该营业执照可激活商户数量达到上限,如需操作请联系管理员");
        }

        return "";
    }
}
